import logging
import os.path
import random
from datetime import datetime

from aiogram import Bot
from aiogram.types import FSInputFile
from arq import ArqRedis
from fluentogram import TranslatorRunner

from src.bot.keyboards.inline import calendar_task_feedback_kb
from src.bot.services.locale import Localizator
from src.bot.services.tg_helpers import broadcast, send_tg_message
from src.bot.worker.exception_handler import exception_handler
from src.config import Settings
from src.core.constants import MESSAGES_MEDIA_FOLDER, TASKS_MEDIA_FOLDER
from src.core.models.enums import UserCalendarStatus
from src.core.utils.date_time import get_date_time
from src.database.services import CalendarService
from src.database.services.user import UserService

logger = logging.getLogger(__name__)


@exception_handler
async def enque_calendar_tasks(
    ctx,
) -> None:
    """Создаем задачи на отправку заданий по календарям в пользовательское время"""

    bot: Bot = ctx["bot"]
    config: Settings = ctx["config"]
    arq_redis: ArqRedis = ctx["redis"]
    localizator: Localizator = ctx["localizator"]
    user_service: UserService = ctx["user_service"]
    calendar_service: CalendarService = ctx["calendar_service"]

    active_users_calendars = await calendar_service.get_active_users_calendars()
    for user_calendar in active_users_calendars:
        calendar = await calendar_service.get_calendar_by_id(user_calendar.calendar_id)
        if len(calendar.tasks) == 0:
            logger.exception(f"В календаре {user_calendar.calendar_id} нет заданий")
            await broadcast(
                bot,
                config.tg_bot.admin_ids,
                f"В календаре {user_calendar.calendar_id} нет заданий",
            )
            continue

        user = await user_service.get_user_by_id(user_calendar.user_id)
        locale: TranslatorRunner = localizator.get_by_locale(user.lang_code)

        cur_date = get_date_time()
        get_tasks_time = datetime.combine(cur_date.date(), user_calendar.get_tasks_time)
        check_tasks_time = datetime.combine(
            cur_date.date(), user_calendar.check_tasks_time
        )
        next_task = user_calendar.tasks_sent + 1
        if user_calendar.tasks_sent == 0:
            next_task = 0

        calendar_title = getattr(
            calendar, f"title_{user.lang_code.value}", calendar.title_ru
        )
        final_message = getattr(
            calendar, f"final_message_{user.lang_code.value}", calendar.final_message_ru
        )

        try:
            task = calendar.tasks[next_task]
            task_text = getattr(
                task, f"task_text_{user.lang_code.value}", task.task_text_ru
            )
            task_file = None
            try:
                task_file_path = os.path.join(TASKS_MEDIA_FOLDER, task.media_filename)
                if os.path.isfile(task_file_path):
                    task_file = FSInputFile(task_file_path)
            except TypeError:
                pass

            await arq_redis.enqueue_job(
                "notify_user",
                user_tg_id=user.telegram_id,
                text=locale.get(
                    "new-calendar-task-msg",
                    calendar_title=calendar_title,
                    task_text=task_text,
                ),
                file=task_file,
                _defer_until=get_tasks_time,
            )
            check_message_file = None
            if len(calendar.check_messages) > 0:
                check_message = random.choice(calendar.check_messages)
                check_message_text = getattr(
                    check_message, f"text_{user.lang_code.value}", check_message.text_ru
                )
                try:
                    check_message_file_path = os.path.join(
                        MESSAGES_MEDIA_FOLDER, check_message.media_filename
                    )
                    if os.path.isfile(check_message_file_path):
                        check_message_file = FSInputFile(check_message_file_path)
                except TypeError:
                    pass
            else:
                check_message_text = locale.get(
                    "check-calendar-task-msg", calendar_title=calendar_title
                )

            await arq_redis.enqueue_job(
                "notify_user",
                user_tg_id=user.telegram_id,
                text=check_message_text,
                file=check_message_file,
                reply_markup=calendar_task_feedback_kb(locale, user_calendar.id),
                _defer_until=check_tasks_time,
            )
            logger.info(
                f"Запланировал задачу по календарю №{user_calendar.id}. Номер задачи: {task.id}"
            )
            await calendar_service.update_calendar_tasks_sended(user_calendar.id)
        except IndexError:
            # Финальное сообщение при прохождении всех заданий
            await send_tg_message(
                bot,
                user.telegram_id,
                locale.get(
                    "calendar-final-msg",
                    calendar_title=calendar_title,
                    final_message=final_message,
                ),
            )
            await calendar_service.update_calendar_status(
                user_calendar.id, UserCalendarStatus.done
            )
